home *** CD-ROM | disk | FTP | other *** search
- /* this file contains some functions for handling the heartbeat. */
-
- #include <sys/types.h>
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <exec/tasks.h>
- #include <exec/interrupts.h>
- #include <devices/timer.h>
- #include <errno.h>
- #include <stdio.h>
- #include <signal.h>
- #include <functions.h>
-
- /* our functions */
- void setup_exception(void);
- int alarm(int);
- void cleanexit(char *, LONG);
- void cleanup_exception(void);
-
- static struct timerequest *treq = NULL;
- static struct MsgPort *tport = NULL;
- static BOOL OpenedTimer = FALSE;
- static int setup = 0;
- int eintr_signal;
-
- extern int comm_time_to_call_heartbeat;
- extern int errno;
-
-
- static void setup_exception()
- {
- /* allocate a signal , used in select() */
- if((eintr_signal = AllocSignal(-1)) == -1)
- cleanexit("Could not allocate EINTR signal\n", RETURN_FAIL);
-
- /* allocate a messageport */
- if(!(tport = CreatePort(0L, 0L)))
- cleanexit("Could not allocate port\n", RETURN_FAIL);
-
- if(!(treq = (struct timerequest *)
- CreateExtIO(tport, sizeof(struct timerequest))))
- cleanexit("Could not allocate message\n",RETURN_FAIL);
-
- /* open the timer device */
- if(OpenDevice("timer.device", UNIT_MICROHZ, (struct IORequest* )treq, 0L))
- cleanexit("Can't open timer device\n", RETURN_FAIL);
-
- OpenedTimer = TRUE;
-
- setup = 1;
- }
-
- /* signal installs a handler for a given signal. */
- void signal(int sig, void (* handler) () )
- {
- register ULONG except_signal;
- register struct Task *this_task;
-
- if(!setup)
- setup_exception();
-
- except_signal = 1L << tport->mp_SigBit;
- this_task = FindTask(NULL);
-
- if(handler == SIG_IGN)
- { /* remove handler */
- except_signal = this_task->tc_SigExcept;
- SetExcept(0L, except_signal);
- cleanup_exception();
- }
- else if(sig == SIGALRM)
- { /* install handler */
- this_task->tc_ExceptCode = (APTR) handler;
- SetExcept(except_signal, except_signal);
- }
- /* else do nothing .. */
- }
-
-
- /* clean up the mess made by a previous alarm, and set a new alarm up */
- int alarm(int seconds)
- {
- while(GetMsg(tport))
- ;
- if(seconds > 0) {
- /* set up the new timer command */
- treq->tr_node.io_Command = TR_ADDREQUEST;
- treq->tr_time.tv_secs = seconds;
- treq->tr_time.tv_micro = 0;
- SendIO((struct IORequest *) treq);
- }
- else
- {
- /* delete out-standing request */
- AbortIO((struct IORequest *) treq);
- WaitIO((struct IORequest *) treq);
- while(GetMsg(tport))
- ;
- }
- return 0;
- }
-
-
- static void cleanexit(char *s, LONG n)
- {
- if(*s) printf(s);
- cleanup_exception();
- exit(n);
- }
-
-
- static void cleanup_exception()
- {
- if(OpenedTimer) CloseDevice((struct IORequest *) treq);
- OpenedTimer = 0;
- if(treq) DeleteExtIO((struct IORequest *) treq);
- treq = 0;
- if(tport) DeletePort(tport);
- tport = 0;
- setup = 0;
- }
-
- /* check if any signals from the sets are available
- * return -1 if failure,
- * 0 if time-out
- * number of ready descriptor otherwise
- * I use the heartbeat as timeout, but according to the UNIX-manual, an
- * interrupted select() returns the unchanged masks. But we already cleared
- * the signals, so the messages would not be read next time. So just save
- * the ready sockets, so we can read them next time.
- */
- int select (width, readfds, writefds, exceptfds, timeout)
- int width;
- register fd_set *readfds, *writefds, *exceptfds;
- struct timeval *timeout;
- {
- static fd_set saved = 0L;
-
- /* find all ready descriptors */
- if(saved) {
- *readfds = saved; /* these were ready the last time already */
- saved = 0L; /* not needed anymore */
- }
- else
- *readfds = Wait(*readfds | eintr_signal);
-
- if(*readfds & eintr_signal) {
- saved = *readfds &~eintr_signal;
- errno = EINTR;
- return -1; /* Failure */
- }
-
- return 1; /* Well, this should be the number of ready descriptors */
- }
-